

section my_code align=16 vstart=0
				
						mov ax, [cs:gdt_start + 0x7c00]
						mov dx, [cs:gdt_start + 2 + 0x7c00]
						mov bx, 16
						div bx
						mov ds, ax ;商 0x7e0
						mov bx, dx ;余数 0

						;建立gdt
						;0#描述符
						mov dword [bx], 0x0
						mov dword [bx + 4], 0x0

						;1#描述符,cs段的描述符,段基址是00007c00,段界限(段的总字节数 - 1)是001ff
						mov dword [bx + 8], 0x7c0001ff
						mov dword [bx + 12], 0x00409a00 ;a主要是让该代码段可读，也就是可以使用cs:前缀来访问

						;2#描述符,es段的描述符，用于输出内容到屏幕,段基址是000b8000,段界限是0ffff
						mov dword [bx + 16], 0x8000ffff
						mov dword [bx + 20], 0x0040920b

						;3#描述符,栈段的描述符,段基址是00000000，段界限是07a00, esp > 07a00
						mov dword [bx + 24], 0x00007a00
						mov dword [bx + 28], 0x00409600

						mov word [cs:gdt_limit + 0x7c00], 31;//设置gdt的界限,32 - 1
						lgdt [cs:gdt_limit + 0x7c00] ;设置gdtr的值

						;打开A20地址线
						in al, 0x92
						or al, 00000010b
						out 0x92, al

						;关闭中断
						cli

						;开启保护模式,此处必须使用eax，因为cr0是32位长度的, 16位代码是可以使用32位寄存器的
						mov eax, cr0
						or eax, 0x01;最后一位设置为1代表开启保护模式
						mov cr0, eax

						;清流水线,此处还是16位代码，但是执行的时候会按照32位执行，编译出来的指令前面会有0x66
						;0x0008会被当作选择子，在gdt中的索引是1, 0000-0000-0000-1000
						jmp dword 0x0008:flush



						;=============================以下代码是32位的===============================
						bits 32 ;以下代码是32位的
						;mov ax, cs
						;mov ds, ax ;保护模式下，不要把代码段赋给数据段，会报错
flush:					mov ax, 0x10 ;0000-0000-0001-0000,在gdt中的索引是2
						mov es, ax
						mov bx, welcome
						mov si, 160 * 12 + 30 * 2
						mov ecx, 23 ;此处不能使用cx，必须使用ecx，cx结果会是错误的
show_lp:				mov al, [cs: bx] ;要想使用前缀访问，段描述符中的type一定要可读,对代码段来说，可以是1010
						mov [es: si], al
						mov byte [es: si + 1], 0x42
						add si, 2
						inc bx
						loop show_lp

						;测试一下栈的使用，栈的位置是0:7c00-----0:7a00
						mov ax, 0000_0000_00_011_000b
						mov ss, ax
						mov esp, 0x7c00
						mov ebp, esp
						push 0x03 ;esp会减4
						sub ebp, 4
						cmp ebp, esp
						jne exit_my
						mov byte [es:si], '!'

exit_my:				hlt


gdt_limit				dw 0x0
gdt_start				dd 0x00007e00
welcome					db 'hello into protect mode'

						times 510-($-$$) db 0
						db 0x55, 0xaa